# -*- coding: utf-8 -*-

from __future__ import division
import os
from datetime import datetime, time, timedelta
from PyQt4.QtCore import QTimer,Qt
from tornado.ioloop import IOLoop
from program_top.utilities.environment_and_platform import environment_initialisation
from program_top.utilities.csv_and_json_serialisation import temperarily_save_a_local_json,clean_load_json
from program_top.utilities.my_datetime import datetime2posix_timestamp, vn_on_order_time

class my_zmq_timer(object):
	'''
	根据zeromq的delayed_callback设计的定时器类
	'''
	def __init__(self,first_emit_moment=datetime.now(),emit_interval=None,emit_function=None,function_parameter=None):
		'''
		首次调用时间：如果不指明，则一构造完毕就立即调用一次，如果指明，则必须为构造之后的某个时点，类型是datetime
		调用时间间隔：如果不指明，则为单次调用，以后再也不调用，如果指明，则每隔此时常调用一次，类型是timedelta
		时间到时调用函数：emit_function，调用此函数的参数
		'''
		self.establish_moment=datetime.now()#定时器创建完成时间
		print '定时器构造时刻:',self.establish_moment
		self.next_emit_moment=first_emit_moment
		print '首次调用时刻:', self.next_emit_moment
		
		self.emit_interval=emit_interval
		self.emit_function=emit_function
		self.function_parameter=function_parameter
		
		if first_emit_moment<=self.establish_moment:#如果没有指定首次调用时间，或者首次调用时间在本实例创建之前，立即调用一次，否则只设定下次调用时间
			self.__time_out()
		else:
			self.__set_single_call(first_emit_moment)
			pass
		
		pass
	
	def __set_single_call(self,time_to_call):
		posix_next_moment=datetime2posix_timestamp(time_to_call)
		IOLoop.instance().call_at(posix_next_moment,self.__time_out)
		pass
	
	def __set_next_call(self):
		'''
		设定下次调用
		'''
		self.next_emit_moment+=self.emit_interval
		self.__set_single_call(self.next_emit_moment)
		pass
		
	def __time_out(self):
		'''时间到，调用函数'''
		
		if self.emit_interval:#如果指定了调用周期，则设定下次调用，否则调用一次就结束
			self.__set_next_call()
		pass
		
		if self.function_parameter:
			self.emit_function(self.function_parameter)
		else:
			self.emit_function()
		
	pass

class my_qt_timer(QTimer):
	def __init__(self,timeout_moment=None,timeout_task=None,repeat_interval=None,**kwargs):
		super(my_qt_timer, self).__init__()

		self.__on_time_task=timeout_task
		self._arguments=kwargs
		self.timeout.connect(self.time_out_task, Qt.QueuedConnection)

		if timeout_moment and timeout_task:#如果指定了要定时做什么任务，就绑定之
			self.setSingleShot(True)#单次触发

			if timeout_moment.__class__.__name__ != 'datetime':
				print '定时器输入类别应该为datetime'
				return
			current_moment=datetime.now()
			if current_moment>timeout_moment:
				print('定时器触发时刻已经在当前时刻之前')
				return
			from_now2timeout=timeout_moment-current_moment
			self.start(1000*from_now2timeout.total_seconds())
			pass

		if repeat_interval and timeout_task:#如果指定了重复周期
			self.setSingleShot(False)
			repeat_interval.total_seconds()
			self.start(repeat_interval.total_seconds()*1000)
			pass
		pass

	def time_out_task(self):
		next_time_parameter=self._arguments['kwargs']

		if next_time_parameter:
			self.__on_time_task(next_time_parameter)
		else:
			self.__on_time_task()

		pass
	pass

class schedule(object):
	'''时间表组件'''
	
	def __init__(self,schedule_config_dict,action):
		super(schedule, self).__init__()
		self.schedule=schedule_config_dict
		self.timeout_action=action
		self.schedule['day_in_week'].sort()#星期排序
		self.schedule["time"]=[datetime.strptime(time_string,vn_on_order_time).time() for time_string in self.schedule["time"]]
		self.schedule['time'].sort()#时点排序
		self.__set_next_moment()
		pass
	
	def __try_find_next_date(self,moment):
		current_date=moment.date()
		current_time=moment.time()
		
		day_in_week=current_date.weekday()#sunday为6，monday为0
		tomorrow_dawn=datetime.combine(current_date, time())+timedelta(days=1)
		
		if day_in_week not in self.schedule['day_in_week']:#如果本日不在时间表当中，切换到下一日
			return self.__try_find_next_date(tomorrow_dawn)
		#本日在时间表当中
		
		for each_time in self.schedule['time']:
			if current_time<each_time:
				return datetime.combine(current_date,each_time)
			pass
		#如果已经走出此循环，说明虽然日期在时间表中，但当前时刻已经大于目标时刻，返回明天的0点后的第一个时刻
		return self.__try_find_next_date(tomorrow_dawn)
	
	def time_out(self):
		'''到时执行，然后设定下次执行'''
		self.timeout_action()
		self.__set_next_moment()
		pass
	
	def __set_next_moment(self):
		'''设定下一次行动'''
		current_moment=datetime.now()
		next_action_time=self.__try_find_next_date(current_moment)
		self.__next_emit_timer=my_zmq_timer(first_emit_moment=next_action_time,emit_function=self.time_out)
		pass
	pass

class timer_loader(object):
	'''定时装载一个main函数，定时卸载一个main函数'''
	
	def __init__(self, main_function, loader_config_json=None):
		environment_initialisation(self)
		config_filename=self._environment_pack['instance_path']['config_file_dir']+"config.json"
		if not os.path.isfile(config_filename):
			temperarily_save_a_local_json({}, config_filename)
		else:
			config_dict=clean_load_json(config_filename)
			pass
		
		end_moments=[datetime.strptime(each_time_string, vn_on_order_time).time() for each_time_string in
		             config_dict['end_moments']]
		start_moments=[datetime.strptime(each_time_string, vn_on_order_time).time() for each_time_string in
		               config_dict['start_moments']]
		self._business_config={'start_moments': start_moments, 'end_moments': end_moments,
			'week_day': config_dict['week_day']}
		self.__update_incoming_schedule()
		pass
	
	def __update_incoming_schedule(self):
		current_moment=datetime.now()
		date_today=current_moment.date()
		time_in_day=current_moment.time()
		
		pass
	
	def load(self):
		'''定时装载'''
		pass
	
	def unload(self):
		'''定时卸载'''
		pass
	
	pass